
#pragma once

#ifndef _SIMPLE_BUTTON_POLLING_H
    #define _SIMPLE_BUTTON_POLLING_H

    #ifndef _BUTTON_LONG_PRESS_THRESHOLD
        // 每次按键扫描周期约8ms，所以长按就是大约1s。阈值最大值为254
        #define _BUTTON_LONG_PRESS_THRESHOLD (120)
    #endif

    #ifndef _BUTTON_DOUBLE_PRESS_THRESHOLD
        // 双击事件的阈值时间，一次点击后，在阈值时间内再次按下按键，触发双击事件
        #define _BUTTON_DOUBLE_PRESS_THRESHOLD (30)
    #endif

    #ifndef _BUTTON_POLL_FILTER_MASK
        // 连续6 次低电平或高电平对应按键按下或抬起
        #define _BUTTON_POLL_FILTER_MASK (0x3f)
    #endif

    #ifndef _BUTTON_POLL_GET_PIN
        #include "stm32f10x_gpio.h"
        #define _BUTTON_POLL_GET_PIN() ((GPIOB->IDR & GPIO_Pin_12))  // PB12
    #endif

// 条件编译开关，关闭按键双击功能，节省代码和内存空间
// #define _BUTTON_POLL_DISABLE_DOUBLE_PRESS

    #ifdef __cplusplus
extern "C" {
    #endif

union _ButtonFlagByte {
    uint8_t flag_byte;  // 可以用flag_byte 同时清零所有标志位

    // 每个成员对应一个标志位，一共8 个标志，刚好放进1 个字节里
    struct {
        uint8_t _pressed : 1;

        // _pressed 和_long_pressed
        // 用于支持扫描函数的内部逻辑，外部不应该直接读取或清零。 带button
        // 前缀的标志位用于传递按键事件，扫描函数只对事件置位，由调用者在响应事件后清零标志位。
        // 除了双击超时事件，每次按键抬起时，双击超时事件都将自动清零
        uint8_t button_pressed : 1;
        uint8_t button_released : 1;
        uint8_t button_clicked : 1;
        uint8_t button_long_pressed : 1;
        uint8_t button_long_press_released : 1;

    #ifndef _BUTTON_POLL_DISABLE_DOUBLE_PRESS
        uint8_t button_double_pressed : 1;
        uint8_t button_double_press_timeout : 1;  
    #endif
    } bits;
};

extern union _ButtonFlagByte poll_button_flag;


#ifndef 

// 集成消抖功能的按键轮询函数
void poll_button(void);

    #ifdef __cplusplus
}
    #endif

#endif